//////////////////////////////////////////////////////////////////////////
//
// GAM203
// Terrain class
// Terrain.h
// 
// Grant Johnson
// Qantm College
// 27/10/2010
//
//////////////////////////////////////////////////////////////////////////

#ifndef TERRAIN_H
#define TERRAIN_H

#include "Drawable.h"
#include <d3d9.h>
#include <d3d9types.h>

#define NUMLIGHTS 5

class Terrain : public Drawable
{
public:
	struct Omni
	{
		D3DXVECTOR3 pos;
		float range;
		D3DXCOLOR diffuse;
		D3DXCOLOR specular;
	} OmniArray[NUMLIGHTS];
	//Struct used to define the type of vertices
	struct VertexData
	{
		D3DVECTOR pos;
		D3DVECTOR normal;
		float u,v;
	};

	//Define Flexible Vertex Format as a static const that is capable of a 3d position
	static const DWORD VERTEX_FORMAT_FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
	
	Terrain(int a_terrainWidth, char* a_pHeightMapFileName);
	Terrain(int a_terrainWidth, float* a_pHeightData, int a_numVerts);
	virtual ~Terrain();

	//////////////////////////////////////////////////////////////////////////
	// VIRTUAL - Inherited from Drawable
	// For creating the drawable object
	//
	// Paramaters:
	// a_pDevice, the direct3d device
	// a_pTexFileName, a path passed into the function. This can either be used for
	// the texture file name, or for a mesh's file name.
	//
	// Returns false if any step of the creation failed
	// Returns true if created successfully
	//
	//////////////////////////////////////////////////////////////////////////
	virtual bool CreateObject(IDirect3DDevice9* a_pDevice, char* a_pTexFileName);

	//////////////////////////////////////////////////////////////////////////
	// VIRTUAL - Inherited from Drawable
	// For rendering the drawable object
	//
	// Paramaters:
	// a_pDevice, the direct3d device
	//
	// Returns void
	//
	//////////////////////////////////////////////////////////////////////////
	virtual void Render(float a_dt, IDirect3DDevice9* a_pDevice, const RenderParams& a_renderParams);

	float GetHeightAtPos(float a_x, float a_z);

	//Used for calculating which terrain chunk the object is in, in order to lerp to it
	//reduce vert count by 1 to give number of quads, this will give the correct sizing
	float GetTerrainWidth() { return (float)(m_gridVertX-1) * m_terrainWidth; }

	ID3DXMesh* GetMesh() const { return m_pMesh; }

	float GetHeight(int a_index) { return m_pHeightData[a_index]; }
	void SetHeight(int a_index, float a_val);

	VertexData GetVertexData(int a_index) { return m_pVertData[a_index]; }
	void SetVertexNormal(int a_index, D3DXVECTOR3 a_val) { m_pVertData[a_index].normal = a_val; }

private:
	
	//////////////////////////////////////////////////////////////////////////
	// Used to create the random height map of the grid
	//
	// Paramaters:
	// None
	//
	// Returns false if it was unable to create the height data
	// Returns true if it was able to create the height data
	//
	//////////////////////////////////////////////////////////////////////////
	bool CreateHeightMap();
	
	//////////////////////////////////////////////////////////////////////////
	// Calculates the lighting normals for each vertex in the terrain
	//
	// Paramaters:
	// None
	//
	// Returns void
	//
	//////////////////////////////////////////////////////////////////////////
	void CalculateNormals();
	
	

protected:
	//Store height map data
	float* m_pHeightData;

	//Number of vertices
	int m_gridVertX;
	int m_gridVertZ;

	//Cell spacing
	int m_terrainWidth;

	//Store the number of vertices, indices and primitives
	long m_vertCount;
	long m_indexCount;
	long m_primCount;

	//Store vertex and index data
	VertexData* m_pVertData;
	unsigned short* m_pIndexData;

	//Store the texture file name
	char* m_pTexFilename;

	//Direct3D texture pointer
	IDirect3DTexture9* m_pTex1;
	IDirect3DTexture9* m_pTex2;
	IDirect3DTexture9* m_pTex3;

	//Material used on the terrain
	D3DMATERIAL9 m_mtl;

	ID3DXMesh* m_pMesh;

};

#endif //TERRAIN_H